package com.zbkj.admin.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.zbkj.admin.constants.AlipayConfig;
import com.zbkj.admin.constants.PayConstants;
import com.zbkj.admin.constants.SysConfigConstants;
import com.zbkj.admin.exception.CrmebException;
import com.zbkj.admin.model.alipay.AliPayInfo;
import com.zbkj.admin.model.order.Order;
import com.zbkj.admin.model.order.OrderDetail;
import com.zbkj.admin.result.PayResultCode;
import com.zbkj.admin.service.*;
import com.zbkj.admin.third_party.BracketSetApi;
import com.zbkj.admin.third_party.vo.BracketSetVo;
import com.zbkj.admin.third_party.vo.DataDTOX;
import com.zbkj.admin.vo.MyRecord;
import jakarta.servlet.http.HttpServletRequest;
import net.dreamlu.mica.core.utils.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 支付宝支付 Service impl
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class AliPayServiceImpl implements AliPayService {

    private static final Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);

    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private AliPayInfoService aliPayInfoService;
    @Autowired
    private BracketSetApi bracketSetApi;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderService orderService;

    /**
     * 支付宝退款
     *
     * @param outTradeNo             支付宝交易号
     * @param refundOrderNo          退款单号
     * @param refundReasonWapExplain 退款说明
     * @param refundPrice            退款金额
     * @return Boolean
     */
    @Override
    public Boolean refund(String outTradeNo, String refundOrderNo, String refundReasonWapExplain, BigDecimal refundPrice) {

        //商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
        //商户订单号，和支付宝交易号二选一
        String out_trade_no = outTradeNo;
        //支付宝交易号，和商户订单号二选一
//        String trade_no = outTradeNo;
        //退款金额，不能大于订单总金额
        String refund_amount = refundPrice.toString();
        //退款的原因说明
        String refund_reason = refundReasonWapExplain;
        //标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
        String out_request_no = refundOrderNo;
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        MyRecord aliPayRecord = getAliPayRecord();
        String aliPayAppid = aliPayRecord.getStr(AlipayConfig.APPID);
        String aliPayPrivateKey = aliPayRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = aliPayRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY);
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);
        AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();

        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(out_trade_no);
        model.setRefundAmount(refund_amount);
        model.setRefundReason(refund_reason);
        model.setOutRequestNo(out_request_no);
        alipay_request.setBizModel(model);
        String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
        alipay_request.setNotifyUrl(apiDomain + PayConstants.ALI_PAY_NOTIFY_API_URI);

        AlipayTradeRefundResponse alipay_response = null;
        try {
            alipay_response = client.execute(alipay_request);
        } catch (AlipayApiException e) {
            logger.error("支付宝退款申请异常，alipay_response = " + alipay_response);
            logger.error(e.getMessage());
            throw new CrmebException("支付宝支付结果异常");
        }
        if ("Y".equals(alipay_response.getFundChange())) {
            return Boolean.TRUE;
        }
        return queryRefund(outTradeNo, refundOrderNo);
    }

    /**
     * 获取支付宝配置
     */
    private MyRecord getAliPayRecord() {
        List<String> list = new ArrayList<>();
        list.add(AlipayConfig.APPID);
        list.add(AlipayConfig.RSA_PRIVATE_KEY);
        list.add(AlipayConfig.ALIPAY_PUBLIC_KEY);
        MyRecord myRecord = systemConfigService.getValuesByKeyList(list);
        if (StrUtil.isBlank(myRecord.getStr(AlipayConfig.APPID))) {
            throw new CrmebException(PayResultCode.ALI_PAY_NOT_CONFIG);
        }
        if (StrUtil.isBlank(myRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY))) {
            throw new CrmebException(PayResultCode.ALI_PAY_NOT_CONFIG);
        }
        if (StrUtil.isBlank(myRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY))) {
            throw new CrmebException(PayResultCode.ALI_PAY_NOT_CONFIG);
        }
        return myRecord;
    }

    /**
     * 支付宝支付
     *
     * @param orderNo    订单号
     * @param price      支付金额
     * @param orderType  订单类型：order - 商品订单，recharge - 充值订单,svip - 付费会员订单
     * @param payChannel 支付渠道：alipayApp - 支付宝app支付, alipay - 支付宝支付
     * @param timeExpire 绝对超时时间，格式为yyyy-MM-dd HH:mm:ss。
     * @return 支付宝调用结果
     */
    @Override
    public String pay(String orderNo, BigDecimal price, String orderType, String payChannel, String timeExpire) {
        if (payChannel.equals(PayConstants.PAY_CHANNEL_ALI_APP_PAY)) {// APP 支付
            return appPay(orderNo, price, orderType, timeExpire);
        }
        if (payChannel.equals(PayConstants.PAY_CHANNEL_ALI_PC_PAY)) {// APP 支付
            return pcPay(orderNo, price, orderType, timeExpire);
        }
        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNo;
        //付款金额，必填
        String total_amount = price.toString();
        //订单名称，必填
        String subject = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
        // 商品描述，可空
        // String body = "用户订购商品个数：1";
        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "30m";

        //获得初始化的AlipayClient
        MyRecord aliPayRecord = getAliPayRecord();
        String aliPayAppid = aliPayRecord.getStr(AlipayConfig.APPID);
        String aliPayPrivateKey = aliPayRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = aliPayRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);

        String returnUrl = "";
        String quitUrl = "";
        String encode = "type=";
        switch (orderType) {
            case "order":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.return_url);
                quitUrl = systemConfigService.getValueByKey(AlipayConfig.quit_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_ORDER);
                break;
            case "recharge":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.recharge_return_url);
                quitUrl = systemConfigService.getValueByKey(AlipayConfig.recharge_quit_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_RECHARGE);
                break;
            case "svip":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.svip_return_url);
                quitUrl = systemConfigService.getValueByKey(AlipayConfig.svip_quit_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_SVIP);
                break;
        }
        //设置请求参数
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
        alipayRequest.setNotifyUrl(apiDomain + PayConstants.ALI_PAY_NOTIFY_API_URI);

        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode("QUICK_WAP_PAY");
        model.setQuitUrl(quitUrl);
        if (StrUtil.isNotBlank(timeExpire)) {
            model.setTimeExpire(timeExpire);
        }

        try {
            encode = URLEncoder.encode(encode, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new CrmebException("支付宝参数UrlEncode异常");
        }
        model.setPassbackParams(encode);

        alipayRequest.setBizModel(model);
        //请求
        String result = "";
        AlipayTradeWapPayResponse response;
        try {
            List<OrderDetail> byOrderNo = orderDetailService.getByOrderNo(out_trade_no);
            Order order = orderService.getByOrderNo(out_trade_no);
            HttpServletRequest request = WebUtil.getRequest();
            String ds = "", url = "";
            if (StrUtil.isNotBlank(request.getHeader("handsome-youg"))) {
                ds = request.getHeader("handsome-youg");
                url = switch (ds) {
                    case "hamstr" -> "http://maiyiqu.hzhuikexin.com";
                    case "puy" -> "http://cshu.hzhuikexin.com:9090";
                    default -> "https://prodapi.huikexin.fun";
                };
            }
            if (StrUtil.isBlank(url)) {
                url = "https://prodapi.huikexin.fun";
            }
            logger.warn("ds:{},url:{}", ds, url);
            LocalDateTime date = LocalDateTime.now();
            DataDTOX data = DataDTOX.builder()
                    .orderNo(out_trade_no)
                    .goodsDesc(byOrderNo.getFirst().getProductName())
                    .tradeType("A_NATIVE")
                    .transAmt(order.getPayPrice().toPlainString())
                    .timeExpire(date.plusMinutes(30))
                    .notifyUrl(url + "/api/publicly/payment/callback/alipay")
//                    .addAcctSplit(DataDTOX.AcctSplitBunch.builder().divAmt(order.getPayPrice().toPlainString()).huifuId("759859892").build())
                    .remark(ds)
                    .build();
            BracketSetVo build = BracketSetVo.builder()
                    .sysId("6666000164543738")
                    .productId("EDUSTD")
                    .keyPri("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChMdbV5i1lARrZFODhsceaeFCwypfIS9rCPjC/6Bq+So4hZBhns2bNAuNxz+ChzkuwGpF5hcFHZTYiQQAz5JvNG63wGg9Z682vv0G6z03JmvFD6K33cDZCKb1s6CpsgURKnP49p/TmqI4eQnrVsAHIdh2cn+JpZ+avd4hSKeINTz2PRmbtVMPQfterjoNmL3rzeb4QFiXgJydQpTG+hQJhKVQDXwcD8X9Wq7cffPZP2IPWnAd7KUE4wYQrX2mz7Z21re5V0QYCJ1in/jk3SSECjEcAVPJ0+/Cp2VU8bMFDTdER6EGU03fZ46HtC7PSU5Gl+9ba+V3E91yQlg1AbxWfAgMBAAECggEBAII2DGFFSq4oslNhdjdasO6q+iOVw/5cqB34ttCO4euNtjpq7Pv4A7bf+nLZhY+vYZykGZec4ICX1Z7d+xfwN5r8HQmzQ2tT/BdX2/TXuPJ+Yx6EOuOClZHkvcvXz01PLqdHImkT39Tjm8n90dQEFaylHU6EKRUUhViAqnIUuzIb4n/EKGW84HTGr6ddLqw7OhEDUSx1CIMnGWUbuWcG6KFOz1AFOPrDlCEgLbapDpVV5OyKAIfwV0zUYvGzAhB7Bela+3LEpIWBSPxICFIk8h1oQhm33nHZ2X3NpmTgg3awsjLBgfZ3Glfm1sONx8kyhzbN2oysf4aGzL4b/XjIkaECgYEA4hP6ISQiiagWO+cQMc3JAIVwGoi+aFCbskKZFe+XypV77zIV28n9Xl7Xkn55PzOTNkfIVtPNaDpeboJmYyEa/0UZmrG2X/JKAJJK7k+CdjUxwNShVCJaUtKreYvpqjEikXyYvLkoU3UeKuBIQX5m45BBcyFjlAZ0VEv7MHNnta0CgYEAtod4kQUJRKclVSgucW0t/JDn4BKAoEtdIQKSWpTM6tl4qanmzn9uAx50WDO8BoAdfB+Nx9Edh39YlSgfNY8uWXs7nhAm1oY2rP3OqNeUgqyTX+HNnTs0uHogM4gXWZMqEG2ywzz+32JFOs4mDwIc/vgq11fU+sNf/KhyuoCsafsCgYEAxsf57pnvJEp/AjywqJngWmz5nNsPUHlP7PVR1U/Nj3rQdgj73z1DYm7R7ST3RvL6RYfoRzAEM9jenxxZGmBJdJo1YSdQzBwlpUr8R33xoC41iO9syqVJ9fj2fPDgi5yYYIPFaGsFYhxgYiLCZZPWs9BrO+fnvofOUTBdtMRENCECgYA+k4seDJ/0zWjbHP9vG4Mch4E3LKC0U6IF4x/RthnamdvoLrtWKBHLN/GjG3lmsR1qpFazHloFTf9Mg4jPj9rQCpORyO/HtBOikxD6iY38jrWntX4MXXPhmtzXTdzTdMSDBVi33n1yj/o0AuDBXHQcZXAqi44Uuk56DDXpApwZaQKBgC/tT36ZpzTwHkSyl4B68nE89OA575SNBSjHr3AzZCIgDi/lgIjAuw41+OKjRGe3YHwgnmMivj8wvgAXXXVWZSsWpYOohfxPb5416gBWcydde9TLFgwHNwEquu6rS07OeJqGvkBcA75OUYVEKQIBfdmz4BLlFLVmzQnyPVJdrvVb")
                    .data(data)
                    .build();
            JSONObject pay = bracketSetApi.pay(build);
/*            AliPayApiConfig aliPayApiConfig = AliPayApiConfig.builder()
                    .setAppId("2021005132662640")
//                    .setAppId(systemConfigService.getValueByKey(AlipayConfig.APPID))
//                .setAppCertPath(aliPayBean.getAppCertPath())
//                .setAliPayCertPath(aliPayBean.getAliPayCertPath())
//                .setAliPayRootCertPath(aliPayBean.getAliPayRootCertPath())
                    .setCharset("UTF-8")
                    // 支付宝小程序
//                    .setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCTY5sEjNQIGYsFGWriEiojif5Tfjb/KPQ1FZbBkHQtJaj9MDK4MeUWpWuWfAKnG0O0hrfmFTZtJQuA8Lrcs2xUdZSbmdA/b9QwrFua55+RT4v41HoSTsnZUScpqqOQt/mE1icV2NLxJn4yqFOWZp+lt/KBtkRijEO7Yxczb2z+L9vADW1ccZ1tJttfRwx/OB6l7K/Dh+JffKGVL9MZwWfYaz4AeM8yCbc2cskRyXr8pkS2tuRnSrE5oW/MfMlsRe2An7CKnTE+zf1qOxnb7WtmayzvAwAY1ts8XjwD8a7OcpYsAy4oYn7S/Sd+YyN/E91+FDbhoVap83eyF0QqPyGnAgMBAAECggEAM5mLi+xBzxQiN4bOhJcXaZnGEDT/zBTqaitEvD92bNficcGOAC53pZYENIr14ssIyQrhFwwWId/2Rw4AXYPzSR5hCJiw74SXJPMynui4VIck2diJZB9xS0O+EjhLSz8dfAP9awid0Q9I3zNPEDida8caf47wIhA5JkFqvfckkVhnuKqVZgDA3iKJKeQQXVfekQSvwgCIUP7Lap16pPIe7MElWRvVEChfVbXsTr98d7GL7hIpsJqotq7Inp4WnequV00sVFflROpIsLFA4n78K55VGcWnYbRdIGyqdGyOr4yi18TqLm25+C8lXaEJzEoPDB5Eg41K1UF4VsVSevdfAQKBgQDN7cc/uF2f5mvBzkHHbM5oBj27Mj+FRXIl+xggvdqz8OOCE3tcRHvwKzF5EWwCu+qo0h/zz5WqO79itiBA4hMX4MGEwf78LTxEy7jE/dca5cWZPSYBv/sASgN1J+fV3+76oJ3mRxlc7atzxQ8DriJj3beCKoEYENT4VHMTmI+YrQKBgQC3OfgvmR6f/k1n+jNked0Vf4NjLSD5SoT9GodkfxslGYP2MBnasZljF98aZJALc/2fHE9EHB8kyjTkl4lIrHXSY5PdkwOtyOp5Hxy8MJDLkGsDiZNuBQBJZe1mchjO+llFcqxPhObaEGtvvkF5pHLG23uVRnVq19JLrlv2uZCKIwKBgG58NrzvU/woioQO/6fZrtyNDK3VBdOhMN9D2uwmMKL+iXIOtc8JR13SLtcAC+1jmUE+i7oqE+ij6ckyYhettATJp8psszvloUJf8yBt+O0Lfnr7Hdsuf6LmEvjWkkJjxTpe1pjoaKk9MxIIFkgpM3ZVTNHfsCeTUFB0LtHCtrh5AoGAdY577g4P2BcREuU0lAKcFm75nWgW/9sP+FRNCe2DPQph4FJ8RBQulaV7PzPGN5Lz5mIDeW+Ri8kwpnmTW01LSvEYrdDlS1rdFVkg1p1SSUkfX+Wk8bHDvVPoPRJ3WFTHcgdhBqP+eWqPg+JNn/4ipfOsFtpd+279PhFgb6wfUIECgYEAnr38Nho2E6NkpG7Z2Zvb8yjtD6kffsJ+RjPYJQ/qylvtQb/zx8ePA1T8abgXTL4AbOYrrmWx5GcjXRiwJBHv+wEk49be92ZCp0O80xckxdhO/9kvrWnNrIpLd9DpzZ72DFFR3ncyxUE1soJMQrzdCnapVYN3QsaPap4PWPnBZVc=")
//                    .setAliPayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk2ObBIzUCBmLBRlq4hIqI4n+U342/yj0NRWWwZB0LSWo/TAyuDHlFqVrlnwCpxtDtIa35hU2bSULgPC63LNsVHWUm5nQP2/UMKxbmuefkU+L+NR6Ek7J2VEnKaqjkLf5hNYnFdjS8SZ+MqhTlmafpbfygbZEYoxDu2MXM29s/i/bwA1tXHGdbSbbX0cMfzgepeyvw4fiX3yhlS/TGcFn2Gs+AHjPMgm3NnLJEcl6/KZEtrbkZ0qxOaFvzHzJbEXtgJ+wip0xPs39ajsZ2+1rZmss7wMAGNbbPF48A/GuznKWLAMuKGJ+0v0nfmMjfxPdfhQ24aFWqfN3shdEKj8hpwIDAQAB")
                    // 支付宝H5
                    .setPrivateKey("""
                            MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKyMZFcddFhmR1JUrpaHch82/E16MFdGCokt+zPxCmE/BxlbEtXwER56A770DAsDkoNCitLJ68Uky5K+O3gYO8MvEieC1xfJoUqTDvS35lz55uK3sl+EJk/EpOBkYxCbHx8Qg9uJRkG3hqtk25VXLvRrAxDXh8REtn9YwKKjw005on74QLIoBQxDfcAc64ABcxjM1aSazdvDdbuwaNz1f/kICSLk+p5YCoVxoUgdW3rl48c2MWC7H9PJQpt69hjN7749BmP+3HQFicmU2qKy22IMBp75nHAqD8gRBH19d2Rw329eihajNz2lLHWyJvs8HuQrDVcck7/8gFZmmi1HILAgMBAAECggEALo8AhReV4osddHdYVElpfghO/LhixleufZ8YUOfdS/nwdgqD7/apQzpzdOfkzz/PTP+CjeYkMoVhm9VvhYZ7jU2Bu9CZXjMw9bF06zJmav1l5wvLOoe4rmw8+UP9lEHuYn48B4i+r37PvOz/0icqcb9DKJGeVAINUgj8PATDQe0kdq7Jzpm7Tkkc78suRlN+wtDnBNo6Onv9Q5rV63wiU+tYMdV7fgFjD3bR7yTFlvjKr3q/7fdjXO1bJN2aMF9m1vejszXZkYj6c1TEMOyTNisJf8WyrTuMwFMJWTopyDtBiZUfR7FckOjQgsHhyr1LLCrxrYp+G/gtPZWkX70UoQKBgQDFO/uPH245Z/7IhaZfR/tIVgH8yhqXYMsFfWnhBI5DwOn2T8BeKreRPns+f1c/Nt3GGw1pBiEO54j3RxpeeTK20rDz3WyTuP3B6W2e6wcuQBFxm52pcwlkZV/kAzmUmLHpGwtioLDaMWGs9OQSeTP+O5BlIICizA67lK02KMgvUwKBgQC0IoY+TpCx2HEYsnVCqU8PMoxmcdlZkpLiFwtWClYiGaaD9UgV7KrQXH4/sj6JaycodqkfJqE+FUAy7J6Vpxrwu3ZRVbzqs6pJzQFxzoZW8Z7hIq1KZLb15A0CfLNHMUQVLUB3vcnDbKb5Mk/i5O15HUJI0EGc2Vxp03+6V5azaQKBgQCP3qIwE1A2xbofEQZ8CCiu6jYG7HGbLHrLZWEfR1By8bx39FKxHd3LL9V8kCzXKrF4+XC9xD/G/HN3VMFSWnv4yhVTvZee5dkMYraYrn4NaaSPx2CpIwWd2yioTQXqc7uK+zRB3E9EybKjE/tt0kVv1IkOizfqCIlSoS/8CqGDiwKBgExLqyxMvoB1OkHJpFzdtTysnkbtxa9oo4nbVNPWgPDkiGCvzR5sJVUnN9nmtxIhLm63A57MD9Np0M1A51Jfesunus9sTx3hhyjHCeuYG9JLeI3G0DsIOW4gb1o0UwK+XSXTCtEss35wULCPnMJvUB3SRLbubjvu3HN+P0U/v/axAoGBAKqfXUeeMh6o1KzSRzsoePeirpEak4NN6WJko0nMd32GksXkp9jr7OxUIryFh0lXoMVuhOox0NQvXoYGh933+6heoNC1Bg6HH8k4ybyNhrlLY2Sgu4UgqVJJnulfnAH8JyjXQ4DuDxpGLCkweEqqoOPoayFMi20XEKHmK2Juvak6
                            """)
                    .setAliPayPublicKey("""
                            MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAisjGRXHXRYZkdSVK6Wh3IfNvxNejBXRgqJLfsz8QphPwcZWxLV8BEeegO+9AwLA5KDQorSyevFJMuSvjt4GDvDLxIngtcXyaFKkw70t+Zc+ebit7JfhCZPxKTgZGMQmx8fEIPbiUZBt4arZNuVVy70awMQ14fERLZ/WMCio8NNOaJ++ECyKAUMQ33AHOuAAXMYzNWkms3bw3W7sGjc9X/5CAki5PqeWAqFcaFIHVt65ePHNjFgux/TyUKbevYYze++PQZj/tx0BYnJlNqisttiDAae+ZxwKg/IEQR9fXdkcN9vXooWozc9pSx1sib7PB7kKw1XHJO//IBWZpotRyCwIDAQAB
                            """)

//                    .setPrivateKey(systemConfigService.getValueByKey(AlipayConfig.RSA_PRIVATE_KEY))
//                    .setAliPayPublicKey(systemConfigService.getValueByKey(AlipayConfig.ALIPAY_PUBLIC_KEY))
                    .setServiceUrl(AlipayConfig.URL)
                    .setSignType("RSA2").build();
            AliPayApiConfigKit.putApiConfig(aliPayApiConfig);
            AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig);*/
//            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
//            model.setOutTradeNo(orderNo);
            try {
                String http = "https://tast.pish.cn/";
                result = pay.getByPath("data.qr_code", String.class);
//                        AliPayApi.wapPayStr(model, http + AlipayConfig.recharge_return_url,
//                        http + AlipayConfig.recharge_quit_url);
//                logger.warn("支付宝查询订单状态，支付宝返回结果：{}", JSONUtil.formatJsonStr(result));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
//            response = alipayClient.pageExecute(alipayRequest);
//            result = response.getBody();
        } catch (Exception e) {
//            logger.error("支付宝订单生成失败," + e.getErrMsg());
//            throw new CrmebException(e.getErrMsg());
        }

        // 保存支付宝订单信息
        AliPayInfo aliPayInfo = new AliPayInfo();
        aliPayInfo.setAppId(aliPayAppid);
        aliPayInfo.setTimestamp(DateUtil.now());
        aliPayInfo.setBody("");
        aliPayInfo.setSubject(subject);
        aliPayInfo.setOutTradeNo(out_trade_no);
        aliPayInfo.setTimeoutExpress(timeout_express);
        aliPayInfo.setTotalAmount(total_amount);
        aliPayInfo.setPassbackParams(model.getPassbackParams());
        aliPayInfo.setNotifyUrl(alipayRequest.getNotifyUrl());
//        aliPayInfo.setCode(Optional.ofNullable(response.getCode()).orElse(""));
//        aliPayInfo.setMsg(Optional.ofNullable(response.getMsg()).orElse(""));
//        aliPayInfo.setSubCode(Optional.ofNullable(response.getSubCode()).orElse(""));
//        aliPayInfo.setSubMsg(Optional.ofNullable(response.getSubMsg()).orElse(""));
//        aliPayInfo.setTradeNo(Optional.ofNullable(response.getTradeNo()).orElse(""));
//        aliPayInfo.setSellerId(Optional.ofNullable(response.getSellerId()).orElse(""));
        aliPayInfoService.save(aliPayInfo);
        return result;
    }

    /**
     * 支付宝App支付
     *
     * @param orderNo    订单号
     * @param price      支付金额
     * @param orderType  订单类型：order - 商品订单，recharge - 充值订单
     * @param timeExpire 绝对超时时间，格式为yyyy-MM-dd HH:mm:ss。
     */
    private String appPay(String orderNo, BigDecimal price, String orderType, String timeExpire) {
        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNo;
        //付款金额，必填
        String total_amount = price.toString();
        //订单名称，必填
        String subject = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
        //商品描述，可空
//            String body = "用户订购商品个数：1";

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "30m";

        //获得初始化的AlipayClient
        MyRecord aliPayRecord = getAliPayRecord();
        String aliPayAppid = aliPayRecord.getStr(AlipayConfig.APPID);
        String aliPayPrivateKey = aliPayRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = aliPayRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setSubject(subject);
        model.setOutTradeNo(out_trade_no);
        model.setTimeoutExpress(timeout_express);
        model.setTotalAmount(total_amount);
        model.setProductCode("QUICK_MSECURITY_PAY");

        String encode = "type=";
        switch (orderType) {
            case "order":
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_ORDER);
                break;
            case "recharge":
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_RECHARGE);
                break;
            case "svip":
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_SVIP);
                break;
        }
        try {
            encode = URLEncoder.encode(encode, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new CrmebException("支付宝参数UrlEncode异常");
        }
        model.setPassbackParams(encode);

        if (StrUtil.isNotBlank(timeExpire)) {
            model.setTimeExpire(timeExpire);
        }

        request.setBizModel(model);
        String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
        request.setNotifyUrl(apiDomain + PayConstants.ALI_PAY_NOTIFY_API_URI);

        //请求
        String result;
        AlipayTradeAppPayResponse response;
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            response = alipayClient.sdkExecute(request);
            result = response.getBody();
        } catch (AlipayApiException e) {
            logger.error("生成支付宝app支付请求异常," + e.getErrMsg());
            throw new CrmebException(e.getErrMsg());
        }
        // 保存支付宝订单信息
        AliPayInfo aliPayInfo = new AliPayInfo();
        aliPayInfo.setAppId(aliPayAppid);
        aliPayInfo.setTimestamp(DateUtil.now());
        aliPayInfo.setBody("");
        aliPayInfo.setSubject(subject);
        aliPayInfo.setOutTradeNo(out_trade_no);
        aliPayInfo.setTimeoutExpress(timeout_express);
        aliPayInfo.setTotalAmount(total_amount);
        aliPayInfo.setPassbackParams(model.getPassbackParams());
        aliPayInfo.setNotifyUrl(request.getNotifyUrl());
        aliPayInfo.setCode(Optional.ofNullable(response.getCode()).orElse(""));
        aliPayInfo.setMsg(Optional.ofNullable(response.getMsg()).orElse(""));
        aliPayInfo.setSubCode(Optional.ofNullable(response.getSubCode()).orElse(""));
        aliPayInfo.setSubMsg(Optional.ofNullable(response.getSubMsg()).orElse(""));
        aliPayInfo.setTradeNo(Optional.ofNullable(response.getTradeNo()).orElse(""));
        aliPayInfo.setSellerId(Optional.ofNullable(response.getSellerId()).orElse(""));
        aliPayInfoService.save(aliPayInfo);
        return result;


    }

    /**
     * 支付宝PC支付
     *
     * @param orderNo    订单号
     * @param price      支付金额
     * @param orderType  订单类型：order - 商品订单，recharge - 充值订单
     * @param timeExpire 绝对超时时间，格式为yyyy-MM-dd HH:mm:ss。
     */
    private String pcPay(String orderNo, BigDecimal price, String orderType, String timeExpire) {
        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNo;
        //付款金额，必填
        String total_amount = price.toString();
        //订单名称，必填
        String subject = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
        //商品描述，可空
        // String body = "用户订购商品个数：1";

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "30m";

        //获得初始化的AlipayClient
        MyRecord aliPayRecord = getAliPayRecord();
        String aliPayAppid = aliPayRecord.getStr(AlipayConfig.APPID);
        String aliPayPrivateKey = aliPayRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = aliPayRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);

        String returnUrl = "";
        String encode = "type=";
        switch (orderType) {
            case "order":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.return_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_ORDER);
                break;
            case "recharge":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.recharge_return_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_RECHARGE);
                break;
            case "svip":
                returnUrl = systemConfigService.getValueByKey(AlipayConfig.svip_return_url);
                encode = encode.concat(PayConstants.PAY_SERVICE_TYPE_SVIP);
                break;
        }

        AlipayTradePrecreateRequest payRequest = new AlipayTradePrecreateRequest();
        payRequest.setReturnUrl(returnUrl);
        String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
        payRequest.setNotifyUrl(apiDomain + PayConstants.ALI_PAY_NOTIFY_API_URI);

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject(subject);
        model.setOutTradeNo(out_trade_no);
        model.setTimeoutExpress(timeout_express);
        model.setTotalAmount(total_amount);

        try {
            encode = URLEncoder.encode(encode, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new CrmebException("支付宝参数UrlEncode异常");
        }
        model.setPassbackParams(encode);

        payRequest.setBizModel(model);

        //请求
        String result;
        AlipayTradePrecreateResponse response;
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            response = alipayClient.execute(payRequest);
        } catch (Exception e) {
            logger.error("生成支付宝PC支付请求异常," + e);
            throw new CrmebException("生成支付宝PC支付请求异常");
        }
        if (!response.isSuccess()) {
            logger.error("生成支付宝PC支付请求失败");
            throw new CrmebException("生成支付宝PC支付请求失败");
        }
        result = response.getQrCode();
        // 保存支付宝订单信息
        AliPayInfo aliPayInfo = new AliPayInfo();
        aliPayInfo.setAppId(aliPayAppid);
        aliPayInfo.setTimestamp(DateUtil.now());
        aliPayInfo.setBody("");
        aliPayInfo.setSubject(subject);
        aliPayInfo.setOutTradeNo(out_trade_no);
        aliPayInfo.setTimeoutExpress(timeout_express);
        aliPayInfo.setTotalAmount(total_amount);
        aliPayInfo.setPassbackParams(model.getPassbackParams());
        aliPayInfo.setNotifyUrl(payRequest.getNotifyUrl());
        aliPayInfo.setCode(Optional.ofNullable(response.getCode()).orElse(""));
        aliPayInfo.setMsg(Optional.ofNullable(response.getMsg()).orElse(""));
        aliPayInfo.setSubCode(Optional.ofNullable(response.getSubCode()).orElse(""));
        aliPayInfo.setSubMsg(Optional.ofNullable(response.getSubMsg()).orElse(""));
        aliPayInfo.setTradeNo("");
        aliPayInfo.setSellerId("");
        aliPayInfoService.save(aliPayInfo);
        return result;
    }

    /**
     * 查询退款
     *
     * @param refundOrderNo 订单编号
     */
    @Override
    public Boolean queryRefund(String outTradeNo, String refundOrderNo) {

        //商户订单号和支付宝交易号不能同时为空。 trade_no、  out_trade_no如果同时存在优先取trade_no
        //商户订单号，和支付宝交易号二选一
        String out_trade_no = outTradeNo;
        //支付宝交易号，和商户订单号二选一
        //        String trade_no = new String(request.getParameter("WIDtrade_no").getBytes("ISO-8859-1"),"UTF-8");
        //请求退款接口时，传入的退款请求号，如果在退款请求时未传入，则该值为创建交易时的外部交易号
        //        String out_request_no = new String(request.getParameter("WIDout_request_no").getBytes("ISO-8859-1"),"UTF-8");
        String out_request_no = refundOrderNo;
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        MyRecord aliPayRecord = getAliPayRecord();
        String aliPayAppid = aliPayRecord.getStr(AlipayConfig.APPID);
        String aliPayPrivateKey = aliPayRecord.getStr(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = aliPayRecord.getStr(AlipayConfig.ALIPAY_PUBLIC_KEY);
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);

        AlipayTradeFastpayRefundQueryRequest alipay_request = new AlipayTradeFastpayRefundQueryRequest();

        AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
        model.setOutTradeNo(out_trade_no);
        model.setOutRequestNo(out_request_no);
        alipay_request.setBizModel(model);
        AlipayTradeFastpayRefundQueryResponse alipay_response = null;
        try {
            alipay_response = client.execute(alipay_request);
        } catch (AlipayApiException e) {
            logger.error("支付宝退款查询异常，alipay_response = " + alipay_response);
            throw new CrmebException("支付宝退款查询异常");
        }
        if (alipay_response.getRefundStatus().equals("REFUND_SUCCESS")) {
            return Boolean.TRUE;
        }
        if (alipay_response.getRefundStatus().equals("REFUND_PROCESSING")) {
            logger.error("支付宝退款查询：退款处理中, outTradeNo = {}", outTradeNo);
            return Boolean.FALSE;
        }
        if (alipay_response.getRefundStatus().equals("REFUND_FAIL")) {
            logger.error("支付宝退款查询：支付宝退款失败, outTradeNo = {}", outTradeNo);
            return Boolean.FALSE;
        }
        logger.error("支付宝退款查询：异常错误");
        return Boolean.FALSE;
    }
}
